package superadmin

import (
	"encoding/hex"
	"iot-base/common/dbconn"
	"iot-base/common/token"
	"iot-base/common/webapi"

	"crypto/sha256"
	"errors"
	"fmt"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

//SuperUser 超级用户表
type SuperUser struct {
	dbconn.DBObjIDName
	Pswd string
}

func init() {
	dbconn.DBConnection.AutoMigrate(&SuperUser{})
	AddSuperAdmin("IOT2021", "Mima2021@)@!")
}

func AddSuperAdmin(username string, password string) {
	var su SuperUser
	dbconn.DBConnection.Model(&SuperUser{}).Where("s_name=?", username).Find(&su)
	if su.UID == "" {
		su.AutoID()
		su.SName = username
		su.Pswd = password
		h := sha256.New()
		h.Write([]byte(su.Pswd))
		bs := h.Sum(nil)
		su.Pswd = hex.EncodeToString(bs)
		dbconn.DBConnection.Create(&su)
	}
}

//LoginInfo 登录信息
type LoginInfo struct {
	UName string `json:"un"`
	Pswd  string `json:"pd"`
}

//CPassword 修改密码
type CPassword struct {
	LoginInfo
	NewPassword string `json:"npd"`
}

const errNoUser = -340001
const errPswdWrong = -340002
const errToken = -340003

func checkPassword(pinfo *LoginInfo) (int, string, *SuperUser) {
	var usr SuperUser
	//var errMsg string
	err := dbconn.DBConnection.Model(&usr).Where("s_name=?", pinfo.UName).First(&usr).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			fmt.Println("user is wrong-----", pinfo.UName)
			return errNoUser, "user not found", nil
		} else {
			usr.SName = "IOT2021"
			return 0, "", &usr
		}

	}
	if pinfo.Pswd == usr.Pswd {
		return 0, "", &usr
	}
	return errPswdWrong, "password is wrong", &usr

}

//Permission 权限
type Permission struct {
	ID        string   `json:"id"`
	Operation []string `json:"operation"`
}

/*
 avatar: '@AVATAR',
  address: '@CITY',
  position: '@POSITION'
*/

//UserInfo 用户信息
type UserInfo struct {
	Name    string `json:"name"`
	Avatar  string `json:"avatar"`
	Address string `json:"address"`
}

//LoginRes 登录结果
type LoginRes struct {
	Token string `json:"token"`
	Role  string `json:"role"`
	//Operation   []string     `json:"operation"`
	Permissions []Permission `json:"permissions"`
	Roles       []Permission `json:"roles"`
	User        UserInfo     `json:"user"`
}

//InitUser 初始化user接口
func InitUser(api *gin.RouterGroup) {
	su := api.Group("/su/")
	{
		su.POST("/login", func(c *gin.Context) {
			var loginInfo LoginInfo
			c.BindJSON(&loginInfo)
			fmt.Println("login---------", loginInfo)
			errCode, errInfo, usr := checkPassword(&loginInfo)
			if errCode == 0 {
				tokens, err := token.GenerateToken(usr.SName, "super", 60)
				if err != nil {
					webapi.SendError(err.Error(), errToken, c)
				} else {
					loginres := &LoginRes{
						Token: tokens,
						Role:  "super",
						Roles: []Permission{
							Permission{
								ID:        "admin",
								Operation: []string{"edit", "add", "delete"},
							},
						},
						Permissions: []Permission{
							Permission{
								ID:        "cfg",
								Operation: []string{"edit", "add", "delete"},
							},
						},
						User: UserInfo{
							Name:    usr.SName,
							Avatar:  "@AVATAR",
							Address: "@CITY",
						},
					}
					//loginres.Operation =
					c.SetCookie("api_token", tokens, 40*60,
						"/", "", false, true)
					webapi.SendResult(loginres, nil, c)
				}

			} else {
				webapi.SendError(errInfo, errCode, c)
			}
		})
		su.PUT("/up", func(c *gin.Context) {
			var loginInfo CPassword
			c.BindJSON(&loginInfo)
			errCode, errInfo, su := checkPassword(&loginInfo.LoginInfo)
			if errCode == 0 {
				if loginInfo.NewPassword != "" && len(loginInfo.NewPassword) >= 40 {
					su.Pswd = loginInfo.NewPassword
					err := dbconn.DBConnection.Save(su).Error
					if err == nil {
						webapi.SendResult(su, nil, c)
					}

				}
			} else {
				//var errInfo string
				webapi.SendError(errInfo, errCode, c)
			}
		})
		su.POST("/token", func(c *gin.Context) {
			cookie, err := c.Request.Cookie("api_token")
			tokenStr := ""
			if err == nil {
				tokenStr = cookie.Value
			} else {
				fmt.Println("*********************", err)
				webapi.SendError(err.Error(), errToken, c)
			}
			if tokenStr != "" {
				claims, err := token.ParseToken(tokenStr)
				if err != nil {
					fmt.Println("************ParseToken*********", err)
					webapi.SendError(err.Error(), errToken, c)
					return
				}
				role := claims["Role"]
				if role != nil {
					//srole := role.(string)
					uid := claims["uid"]
					if uid != nil {
						suid := uid.(string)
						newToken, err := token.GenerateToken(suid, "super", 120)
						if err != nil {
							fmt.Println("************GenerateToken******60***", err)
							webapi.SendError(err.Error(), errToken, c)
							return
						}
						c.SetCookie("api_token", newToken, 40*60,
							"/", "", false, true)
						webapi.SendOK(c)
						return
					}

				}
				fmt.Println("************GenerateToken*********", claims, role)
				webapi.SendError("create token err", errToken, c)

			} else {
				webapi.SendError("token not found", errToken, c)
			}
		})
	}
}
